package com.laterem.rtc.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.laterem.rtc.dao.*;
import com.laterem.rtc.domain.*;
import com.laterem.rtc.service.UserService;
import com.laterem.rtc.service.dto.WeChatTokenDTO;
import com.laterem.rtc.service.dto.WechatOpenIdDTO;
import com.laterem.rtc.util.UserHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @creator: alan wu
 * @dateTime: 2023/5/20 01:34
 * @desc:
 */
@Service
@SuppressWarnings("all")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private ActivityMapper activityMapper;

    @Autowired
    private ActivityItemMapper activityItemMapper;

    @Autowired
    private UserActivityItemLogMapper userActivityItemLogMapper;

    @Autowired
    private ConfigurationMapper configurationMapper;

    @Override
    public String login(String username, String password, Integer type) {
        UserDO userDO = userMapper.selectOne(new QueryWrapper<UserDO>().eq("username", username)
                .eq("password", password).eq("user_type", type));
        if (!Objects.isNull(userDO)){
            String uuid = UUID.randomUUID().toString();
            UserHolder.putUserDO(uuid, userDO);
            return uuid;
        }
        return null;
    }

    @Override
    public IPage<UserDO> userList(Page page) {
        Page<UserDO> userPage = userMapper.selectPage(page, new QueryWrapper<UserDO>().orderByDesc("create_time"));
        return userPage;
    }


    public static final String APPKEY = "fc97a182986bf0c3";// 你的appkey
    public static final String URL = "https://api.jisuapi.com/shouji/query";
    public static final String shouji = "13456755448";
   //  https://api.jisuapi.com/shouji/query?appkey=fc97a182986bf0c3&shouji=13456755448
    public void Get(String cellphone) {

//        String result = null;
//        String url = URL + "?appkey=" + APPKEY + "&shouji=" + shouji;
//
//        try {
//            result = HttpUtil.sendGet(url, "utf-8");
//            JSONObject json = JSONObject.fromObject(result);
//            if (json.getInt("status") != 0) {
//                System.out.println(json.getString("msg"));
//            } else {
//                JSONObject resultarr = json.optJSONObject("result");
//                String province = resultarr.getString("province");
//                String city = resultarr.getString("city");
//                String company = resultarr.getString("company");
//                String cardtype = resultarr.getString("cardtype");
//                System.out.println(province + " " + city + " " + company + " " + cardtype);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    @Override
    public JSONArray location(String cellphone) {
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForEntity("http://c96ed3dd.api.cn/mobile/?token=283c43bfd814bf8ef90adbc0a0fc981d&mobile=" + cellphone,
                String.class).getBody();
        result = result.replace("\\", "");
        JSONObject jsonObject = JSONObject.parseObject(result);
        JSONArray array = (JSONArray)jsonObject.get("data");
        return array;
    }

    @Override
    public void save(UserDO userDO) {
        userMapper.insert(userDO);
    }

    @Override
    public void update(UserDO userDO) {
        userMapper.updateById(userDO);
    }

    @Override
    public void delete(Integer id) {
        userMapper.deleteById(id);
    }

    @Override
    public synchronized String wechatLogin(UserDO userDO) {
        String openId = getOpenId(userDO.getCode());
        if (StringUtils.isEmpty(openId)){
            throw new RuntimeException("获取openId失败");
        }
        UserDO selectOne = userMapper.selectOne(new QueryWrapper<UserDO>().eq("open_id", openId));
        if (Objects.isNull(selectOne)){
            userDO.setCreateTime(LocalDateTime.now(ZoneId.of("GMT+8")));
            userDO.setOpenId(openId);
            userDO.setCellphone("");
            userDO.setIdCard("");
            userDO.setRealName("");
            userMapper.insert(userDO);
        } else {
            BeanUtils.copyProperties(userDO, selectOne);
            userMapper.updateById(selectOne);
        }
        return openId;
    }

    @Override
    public String adminLogin(String username, String password) {
        AdminDO adminDO = adminMapper.selectOne(new QueryWrapper<AdminDO>().eq("username", username).eq("password", password));
        if (!Objects.isNull(adminDO)){
            return UUID.randomUUID().toString();
        }
        return null;
    }

    @Override
    public void saveActivity(ActivityDO activityDO) {
        activityDO.setActivityStatus(1);
        activityMapper.insert(activityDO);
    }

    @Override
    public void updateActivity(ActivityDO activityDO) {
        activityMapper.updateById(activityDO);
    }

    @Override
    public IPage<ActivityDO> activityList(Page page) {
        Page data = activityMapper.selectPage(page, new QueryWrapper<ActivityDO>().orderByDesc("activity_date"));
        List<ActivityDO> dataRecords = data.getRecords();
        if (!CollectionUtils.isEmpty(dataRecords) && dataRecords.size() > 0) {
            dataRecords.forEach(item -> {
                Integer activityId = item.getId();
                List<ActivityItemDO> activityItemDOList = activityItemMapper.selectList(new QueryWrapper<ActivityItemDO>()
                        .eq("activity_id", activityId));
                //统计轮次的参与信息
                if(!CollectionUtils.isEmpty(activityItemDOList)){
                    activityItemDOList.forEach(itemDO -> {
                        Integer itemDOId = itemDO.getId();
                        List<UserActivityItemLogDO> userActivityItemLogDOList = userActivityItemLogMapper
                                .selectList(new QueryWrapper<UserActivityItemLogDO>().eq("activity_item_id", itemDOId));
                        if (!CollectionUtils.isEmpty(userActivityItemLogDOList)){
                            long count1 = userActivityItemLogDOList.stream().filter(userActivityItemLogDO -> userActivityItemLogDO.getGuessResult().equals(1)).count();
                            long count2 = userActivityItemLogDOList.stream().filter(userActivityItemLogDO -> userActivityItemLogDO.getGuessResult().equals(2)).count();
                            Map<String, Object> countData = new HashMap<>();
                            countData.put("1", count1);
                            countData.put("2", count2);
                            itemDO.setData(countData);
                        }
                    });
                }
                item.setActivityItemDOList(activityItemDOList);
            });
        }
        return data;
    }

    @Override
    public void deleteActivity(Integer id) {
        activityMapper.deleteById(id);
        activityItemMapper.delete(new QueryWrapper<ActivityItemDO>().eq("activity_id", id));
    }

    @Override
    public void saveActivityItem(ActivityItemDO activityItemDO) {
        activityItemMapper.insert(activityItemDO);
    }

    @Override
    public void updateActivityItem(ActivityItemDO activityItemDO) {
        ActivityItemDO itemDO = activityItemMapper.selectById(activityItemDO.getId());
        if (Objects.isNull(itemDO)){
            throw new RuntimeException("轮次不存在");
        }
        Integer result = activityItemDO.getResult();
        if (!Objects.isNull(result) && LocalDateTime.now(ZoneId.of("GMT+8")).isBefore(itemDO.getEndTime())){
            throw new RuntimeException("本轮还未结束");
        }
        // 更新设置了答案
        if (!Objects.isNull(result)) {
            List<UserActivityItemLogDO> userActivityItemLogDOList = userActivityItemLogMapper
                    .selectList(new QueryWrapper<UserActivityItemLogDO>().eq("activity_item_id", activityItemDO.getId()));
            if (!CollectionUtils.isEmpty(userActivityItemLogDOList)) {
                // 更新用户参加的信息
                userActivityItemLogDOList.forEach(item -> {
                    item.setActivityItemResult(result);
                    userActivityItemLogMapper.updateById(item);
                });
                // 更新场次信息
                // 猜中的人数
                AtomicInteger hintCount = new AtomicInteger(0);
                AtomicReference<String> winnerOpenId = new AtomicReference<>();
                userActivityItemLogDOList.forEach(log -> {
                    if (log.getGuessResult().equals(log.getActivityItemResult())) {
                        winnerOpenId.set(log.getOpenId());
                        hintCount.incrementAndGet();
                    }
                });
                // 根据猜中的人数设定游戏的状态，比如猜中的人为0，则流局。
                if (hintCount.get() == 0) {
                    ActivityDO activityDO = new ActivityDO();
                    activityDO.setId(itemDO.getActivityId());
                    activityDO.setActivityStatus(3);
                    activityMapper.updateById(activityDO);
                } else if (hintCount.get() == 1) {
                    ActivityDO activityDO = new ActivityDO();
                    activityDO.setId(itemDO.getActivityId());
                    activityDO.setActivityStatus(2);
                    activityDO.setOpenId(winnerOpenId.get());
                    activityMapper.updateById(activityDO);
                } else if (hintCount.get() > 1) {
                    // 自动新增一个轮次
                    List<ActivityItemDO> activityItemDOList = activityItemMapper.selectList(new QueryWrapper<ActivityItemDO>().eq("activity_id", itemDO.getActivityId()).orderByDesc("end_time"));
                    ActivityItemDO lastRound = activityItemDOList.get(0);
                    ActivityItemDO newRound = new ActivityItemDO();
                    newRound.setStartTime(lastRound.getEndTime());
                    // 默认新增5分钟
                    newRound.setEndTime(lastRound.getEndTime().plusMinutes(3));
                    newRound.setActivityId(lastRound.getActivityId());
                    activityItemMapper.insert(newRound);
                }
            }
        }
       activityItemMapper.updateById(activityItemDO);
    }

    @Override
    public void deleteActivityItem(Integer id) {
      activityItemMapper.deleteById(id);
    }

    @Override
    public void bet(Integer activityItemId, Integer guessResult, String openId) {
        // 检测用户是否可以下注
        // 1.用户是否已下注
        UserActivityItemLogDO userActivityItemLogDO = userActivityItemLogMapper
                .selectOne(new QueryWrapper<UserActivityItemLogDO>()
                        .eq("activity_item_id", activityItemId).eq("open_id", openId));
        if (!Objects.isNull(userActivityItemLogDO)){
            throw new RuntimeException("请勿重复下注！");
        }
        //2. 用户是否参与了上一次的下注并且猜中
        ActivityItemDO activityItemDO = activityItemMapper.selectById(activityItemId);
        // 2.1 是否超过最晚下注时间
        LocalDateTime now = LocalDateTime.now(ZoneId.of("GMT+8"));
        if (now.isAfter(activityItemDO.getEndTime())){
            throw new RuntimeException("本轮下注已结束！");
        }
        if (now.isBefore(activityItemDO.getStartTime())){
            throw new RuntimeException("本轮下注还未开始！");
        }
        Integer activityId = activityItemDO.getActivityId();
        List<ActivityItemDO> activityItemDOList = activityItemMapper.selectList(new QueryWrapper<ActivityItemDO>().eq("activity_id", activityId).orderByDesc("end_time"));
        // 2.2 如果是第一轮，则无需校验
        if (activityItemDOList.size() == 1){
            UserActivityItemLogDO logDO = new UserActivityItemLogDO();
            logDO.setActivityItemId(activityItemId);
            logDO.setOpenId(openId);
            logDO.setGuessResult(guessResult);
            logDO.setCreateTime(now);
            userActivityItemLogMapper.insert(logDO);
        }
        // 2.2 如果轮次大于1，则需要判断是否参与上一个场次并且猜对
        if (activityItemDOList.size() > 1){
            ActivityItemDO itemDO = activityItemDOList.get(1);
            Integer id = itemDO.getId();
            UserActivityItemLogDO userLogDO = userActivityItemLogMapper
                    .selectOne(new QueryWrapper<UserActivityItemLogDO>()
                            .eq("activity_item_id", id).eq("open_id", openId));
            if (!Objects.isNull(userLogDO) && userLogDO.getGuessResult().equals(userLogDO.getActivityItemResult())){
                UserActivityItemLogDO logDO = new UserActivityItemLogDO();
                logDO.setActivityItemId(activityItemId);
                logDO.setOpenId(openId);
                logDO.setGuessResult(guessResult);
                logDO.setCreateTime(now);
                userActivityItemLogMapper.insert(logDO);
            } else {
                throw new RuntimeException("你不符合参与条件！");
            }
        }
    }

    @Override
    public ActivityDO activity(String openId) {
        Optional<ActivityDO> activityDOOptional = activityMapper.selectList(new QueryWrapper<ActivityDO>()
                .orderByDesc("activity_date")).stream().findFirst();
        ActivityDO activityDO = activityDOOptional.get();
        if (!Objects.isNull(activityDO)){
            Integer id = activityDO.getId();
            List<ActivityItemDO> activityItemDOList = activityItemMapper.selectList(new QueryWrapper<ActivityItemDO>()
                    .eq("activity_id", id).orderByDesc("end_time"));
            if (!CollectionUtils.isEmpty(activityItemDOList)){
                activityItemDOList.forEach(itemDO -> {
                    Integer itemDOId = itemDO.getId();
                    UserActivityItemLogDO logDO = userActivityItemLogMapper.selectOne(
                            new QueryWrapper<UserActivityItemLogDO>().eq("activity_item_id", itemDOId).eq("open_id", openId));
                    if (!Objects.isNull(logDO)){
                        itemDO.setUserResult(logDO.getGuessResult());
                    }
                    // 2023.06.10新增字段，用于前端展示
                    List<UserActivityItemLogDO> activityItemLogDOList = userActivityItemLogMapper
                            .selectList(new QueryWrapper<UserActivityItemLogDO>().eq("activity_item_id", itemDOId));
                });
            }
            activityDO.setActivityItemDOList(activityItemDOList);
        }
        return activityDO;
    }

    @Override
    public void updateJackpot(Integer number) {
        ConfigurationDO configurationDO = new ConfigurationDO();
        configurationDO.setLabelValue(String.valueOf(number));
       configurationMapper.update(configurationDO, new QueryWrapper<ConfigurationDO>().eq("label_name", "jackpot"));
    }

    @Override
    public String selectJackpot() {
        ConfigurationDO configurationDO = configurationMapper.selectOne(new QueryWrapper<ConfigurationDO>().eq("label_name", "jackpot"));
        return configurationDO.getLabelValue();
    }

    @Override
    public String getOpenId(String code) {
        return getWxOpenId(code);
    }

    @Override
    public void updateUser(UserDO userDO) {
        userMapper.updateById(userDO);
    }

    @Override
    public UserDO getUserInfo(String openId) {
        return userMapper.selectOne(new QueryWrapper<UserDO>().eq("open_id", openId));
    }

    @Override
    public ActivityItemDO newActivityItem(String openIdStr) {
        // 查询当前用户信息
        UserDO userDO = getUserInfo(openIdStr);
        ActivityItemDO activityItemDO = activityItemMapper.newActivityItem();
        if (!Objects.isNull(activityItemDO)){
            List<ActivityItemDO> activityItemDOList = activityItemMapper.selectList(new QueryWrapper<ActivityItemDO>().eq("activity_id", activityItemDO.getActivityId()).orderByDesc("end_time"));
            int totalRound = activityItemDOList.size();
            int leftPeople = 0;
            // 如果大于1。则证明有上一场的数据
            if (totalRound > 1){
                ActivityItemDO lastActivityItemDO = activityItemDOList.get(1);
                List<UserActivityItemLogDO> lastUserActivityItemLogDOList = userActivityItemLogMapper.selectList(new QueryWrapper<UserActivityItemLogDO>().eq("activity_item_id", lastActivityItemDO.getId()));
                leftPeople = (int) lastUserActivityItemLogDOList.stream().filter(item -> item.getGuessResult().equals(item.getActivityItemResult())).count();
                // 遍历数据
                lastUserActivityItemLogDOList.forEach(item -> {
                    if (item.getOpenId().equals(openIdStr) && item.getGuessResult().equals(item.getActivityItemResult())){
                        activityItemDO.setDrawResult(2);
                    } else if (item.getOpenId().equals(openIdStr) && !item.getGuessResult().equals(item.getActivityItemResult())){
                        activityItemDO.setDrawResult(3);
                    }
                });
            } else {
                activityItemDO.setDrawResult(1);
            }
            Integer id = activityItemDO.getId();
                List<UserActivityItemLogDO> userActivityItemLogDOList = userActivityItemLogMapper.selectList(new QueryWrapper<UserActivityItemLogDO>().eq("activity_item_id", id));
                if (!CollectionUtils.isEmpty(userActivityItemLogDOList)){
                 // 设置统计数据
                    int total = userActivityItemLogDOList.size();
                    int right = (int) userActivityItemLogDOList.stream().filter(item -> item.getGuessResult().equals(item.getActivityItemResult())).count();
                    int oneCount = (int)userActivityItemLogDOList.stream().filter(item -> item.getGuessResult() == 1).count();
                    int twoCount = (int)userActivityItemLogDOList.stream().filter(item -> item.getGuessResult() == 2).count();
                    // 报名总人数
                    activityItemDO.setTotalUser(total);
                    // 第几轮
                    activityItemDO.setRound(totalRound);
                    //  本轮猜对人数
                    activityItemDO.setCountWinner(right);
                    // 选1的人数
                    activityItemDO.setChooseOne(oneCount);
                    // 选2的人数
                    activityItemDO.setChooseTwo(twoCount);
                    // 上把剩余的人数
                    activityItemDO.setLeftUser(leftPeople);
                } else {
                    // 报名总人数
                    activityItemDO.setTotalUser(0);
                    // 第几轮
                    activityItemDO.setRound(totalRound);
                    //  本轮猜对人数
                    activityItemDO.setCountWinner(0);
                    // 选1的人数
                    activityItemDO.setChooseOne(0);
                    // 选2的人数
                    activityItemDO.setChooseTwo(0);
                    // 上把剩余的人数
                    activityItemDO.setLeftUser(leftPeople);
                }
          }
        return activityItemDO;
    }

    private String getWxOpenId(String code){
        RestTemplate restTemplate = new RestTemplate();
        String forEntity = restTemplate.getForEntity("https://api.weixin.qq.com/sns/jscode2session?appid=wx22288bed5547ab9b&secret=e7505f00ac087a50666f99f4df7f3cd8&js_code=" + code + "&grant_type=authorization_code", String.class).getBody();
        return JSONObject.parseObject(forEntity, JSONObject.class).get("openid").toString();
//        return forEntity.getBody().getOpenpid();
    }

    private String getWechatOpenId(String code) {
        RestTemplate restTemplate = new RestTemplate();
        WeChatTokenDTO weChatTokenDTO = restTemplate.getForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx22288bed5547ab9b&secret=e7505f00ac087a50666f99f4df7f3cd8",
                WeChatTokenDTO.class).getBody();
        String accessToken = weChatTokenDTO.getAccess_token();
        Map<String, Object> postData = new HashMap<>();
        postData.put("code", code);
        WechatOpenIdDTO wechatOpenIdDTO = restTemplate.postForEntity("https://api.weixin.qq.com/wxa/getpluginopenpid?access_token=" + accessToken, postData, WechatOpenIdDTO.class).getBody();
        return wechatOpenIdDTO.getOpenpid();
    }

    private String getWechatToken(){
        RestTemplate restTemplate = new RestTemplate();
        WeChatTokenDTO weChatTokenDTO = restTemplate.getForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=",
                WeChatTokenDTO.class).getBody();
        return weChatTokenDTO.getAccess_token();
    }
}
